function [fun, grad, norm_grad, extra] = PL_objective_function(...
    X, indices, size_images, data, operator, adjoint, method, mu, alpha, beta)
% [fun, grad, norm_grad, extra] = PL_objective_function(...
%    X, indices, size_images, data, operator, adjoint, method, mu, alpha, beta)
% 
% PL_objective_function is the objective function used for 
% denoising and demosaicking of colour images with uncorrelated, white
% Gaussian noise.
%
% 2013-07-25 --------------------------------------------------------------
% 
% Matthias J. Ehrhardt
% CMIC, University College London, UK
% 
% matthias.ehrhardt.11@ucl.ac.uk
% 
% -------------------------------------------------------------------------

    x = Vec2struct(X, indices, size_images);
    
    fun_parts = zeros(2,1);
    Norm = @(x) (norm(x(:), 2));    
    
    if alpha > 0       
        [fun_, grad_] = PL_penalty(method, beta, x);

        fun_parts(2) = alpha * fun_;
        grad = alpha * grad_;
    else
        grad = zeros(size(x));
    end
        
    if mu > 0
        r = operator(Struct2im(x)) - data;
        fun_image = 0.5 * abs(r).^2;
   
        if nargout > 1
            grad = grad + mu * Column(adjoint(r));       
        end

        fun_parts(1) = mu * sum(fun_image(:));
    end
    
    fun = sum(fun_parts);
    norm_grad = Norm(grad);
    
    extra.fun_parts = fun_parts;
end